In [1]:
import time
import os
import sys
import numpy as np
import matplotlib
matplotlib.use('nbagg')
#from matplotlib import style
#style.use('ggplot')
import matplotlib.pyplot as plt
import astropy.units as u
from astropy import stats, wcs
from astropy.io import fits
from astropy.convolution import Gaussian2DKernel
from astropy.coordinates import SkyCoord
from mmtwfs.wfs import *
from mmtwfs.zernike import ZernikeVector
from mmtwfs.telescope import MMT
import poppy
import photutils
In [2]:
%load_ext autoreload
%autoreload 2
In [18]:
sys.path.append("/Users/tim/src/cwfs/python")
%cd /Users/tim/MMT/61_inch/20181219/
In [19]:
from lsst.cwfs.instrument import Instrument
from lsst.cwfs.algorithm import Algorithm
from lsst.cwfs.image import Image, readFile
import lsst.cwfs.plots as plots
In [49]:
r = 60
extra_whole = fits.open("rts2focus0012.fits")[1].data # focus = 3190
intra_whole = fits.open("rts2focus0017.fits")[1].data # focus = 1992
#intra = intra_whole[942-18:942+18,158-18:158+18] - np.median(intra_whole)
#extra = extra_whole[945-18:945+18,154-18:154+18] - np.median(extra_whole)
intra = intra_whole[780-r:780+r,503-r:503+r] - np.median(intra_whole)
extra = extra_whole[780-r:780+r,509-r:509+r] - np.median(extra_whole)
In [50]:
#plt.imshow(intra_whole[942-20:942+20,158-20:158+20], origin="lower")
#plt.imshow(extra_whole[945-20:945+20,154-20:154+20], origin="lower")
plt.imshow(intra, origin="lower")
plt.show()
In [6]:
plt.imshow(extra, origin="lower")
plt.show()
In [51]:
fits.writeto("intra.fits", intra, overwrite=True)
fits.writeto("extra.fits", extra, overwrite=True)
These images are binned 3x3 so the pixels are 42 um. Thus the pupil diameter is:
In [34]:
pupsize = 25.25 * 3 * 14
pupsize * u.um
Out[34]:
The mirror diameter is 1.54 meters and the focal ratio is 13.5. So the focal length is:
In [35]:
diameter = 1.54 * u.m
radius = diameter / 2.
focal_length = diameter * 13.5
focal_length
Out[35]:
Calculate the angle of beam convergence:
In [36]:
ang = np.arctan2(radius, focal_length)
ang
Out[36]:
In [37]:
offset = pupsize / np.tan(ang) * u.um
offset
Out[37]:
In [12]:
def kuiper_focus(pup_rad, focus, binning=3, direction='out'):
pupsize = 14 * binning * pup_rad * u.um
diameter = 1.54 * u.m
radius = diameter / 2
focal_length = diameter * 13.5
beam_ang = np.arctan2(radius, focal_length)
offset = pupsize / np.tan(beam_ang) * u.um
counts_per_um = 600. / 28633.5 # empirically determined
correction = offset.value * counts_per_um
if 'out' in direction:
correction *= -1
return focus + correction
In [13]:
kuiper_focus(25.25, 3190, direction='out')
Out[13]:
So about 14 mm of focus offset at focal plane for 300 counts of focus change which gives 20 counts/mm. For motion at the secondary, scale by the ratio of the squares of the focal ratios:
In [14]:
counts_per_mm = 600. / offset.to(u.mm).value
counts_per_mm_m2 = counts_per_mm / (13.5**2 / 4.**2)
counts_per_mm, counts_per_mm_m2
Out[14]:
In [15]:
obscuration = 0.4096 / 1.54
obscuration
Out[15]:
In [16]:
nmperrad = radius.to(u.nm).value
nmperasec = nmperrad / 206265.
nmperasec
Out[16]:
In [52]:
fieldXY = [0., 0.]
I1 = Image(readFile("intra.fits"), fieldXY, Image.INTRA)
I2 = Image(readFile("extra.fits"), fieldXY, Image.EXTRA)
In [53]:
fig, ax = plt.subplots()
im = ax.imshow(I2.image, origin='lower', cmap='RdBu')
cbar = fig.colorbar(im)
fig.show()
In [54]:
kuiper = Instrument('61inch', I1.sizeinPix)
In [55]:
#kuiper.offset = offset.to(u.m).value # needs to be focus offset between intra and extra positions
kuiper.offset
Out[55]:
In [56]:
algo = Algorithm('exp', kuiper, 3)
In [57]:
algo.runIt(kuiper, I1, I2, 'onAxis')
In [26]:
print(algo.zer4UpNm)
In [58]:
plots.plotZer(algo.zer4UpNm, 'nm')
In [59]:
zv = ZernikeVector()
zv.from_array(algo.zer4UpNm, modestart=4, normalized=True)
zv.denormalize()
zv
Out[59]:
In [60]:
zv.fringe_bar_chart().show()
plt.show()
In [61]:
plots.plotImage(algo.Wconverge, "Final wavefront", show=True)
In [62]:
plt.imshow(algo.image)
plt.show()
In [ ]:
plt.close('all')
Scaling seems wrong so try to calculate offset for MMT same way...
In [31]:
pupsize = 135. * 26.
diameter = 6.5 * u.m
radius = diameter / 2.
focal_length = diameter * 5.3
mmt_ang = np.arctan2(radius, focal_length)
offset = 0.5 * pupsize / np.tan(mmt_ang) * u.um
offset
Out[31]:
OK, this matches what we're using there.
Use the Z04 term from the CWFS fit and see if we can calculate a focus correction
In [38]:
# this calculates the difference in size between in-focus pupil and observed in um
foc_err = (zv['Z04'] / (nmperasec * u.nm / u.arcsec)) * (100 * u.um / u.arcsec)
# use the tangent of the beam angle to convert pupil size difference to shift in focus position at focal plane.
# convert to focus counts and negate to create correction to send to telescope.
foc_corr = -counts_per_mm * foc_err.to(u.mm).value / np.tan(ang)
foc_corr
Out[38]:
In [64]:
from astropy.nddata import CCDData
from artnfocus.imutils import ARTNreduce, sub_background, find_donuts
In [72]:
im = ARTNreduce("rts2focus0012.fits")
#im.data = sub_background(im)
norm = wfs_norm(im)
plt.subplot(projection=im.wcs)
plt.imshow(im, origin='lower', norm=norm)
plt.xlabel('RA')
plt.ylabel('Dec')
plt.show()